// TO-DO : ver que pasa con la inicializacion de currentDirection.

package tp.pr4;

import tp.pr4.instructions.exceptions.InstructionExecutionException;
import tp.pr4.items.Item;

/**
 * This class is in charge of the robot navigation features. It contains the
 * city where the robot looks for garbage, the current place where the robot is,
 * and the current direction of the robot. It contains methods to handle the
 * different robot movements and to pick and drop items at the current place.
 * 
 */
public class NavigationModule {

	private City cityMap;
	private Place currentPlace;
	private Direction currentDirection;

	/**
	 * Navigation module constructor. It needs the city map and the initial
	 * place
	 * 
	 * @param aCity
	 *            - A city map
	 * @param initialPlace
	 *            - An initial place for the robot
	 */
	public NavigationModule(City aCity, Place initialPlace) {
		this.cityMap = aCity;
		this.currentPlace = initialPlace;
	}

	/**
	 * Checks if the robot has arrived at a spaceship
	 * 
	 * @return true if an only if the current place is the spaceship
	 */
	public boolean atSpaceship() {
		return currentPlace.isSpaceship();
	}

	/**
	 * Updates the current direction of the robot according to the rotation
	 * 
	 * @param rotation
	 *            - left or right
	 */
	public void rotate(Rotation rotation) {
		if (rotation == Rotation.LEFT)
			currentDirection = currentDirection.rotateLeft();
		else if (rotation == Rotation.RIGHT)
			currentDirection = currentDirection.rotateRight();

	}

	/**
	 * The method tries to move the robot following the current direction. If
	 * the movement is not possible because there is no street, or there is a
	 * street which is closed, then it throws an exception. Otherwise the
	 * current place is updated according to the movement
	 * 
	 * @throws InstructionExecutionException
	 *             - An exception with a message about the encountered problem
	 */
	public void move() throws InstructionExecutionException {

		Street st = getHeadingStreet();

		if (st == null)
			throw new InstructionExecutionException(
					"No existe calle en tal direccion");
		else if (!st.isOpen())
			throw new InstructionExecutionException("La calle está cerrada");
		else
			currentPlace = st.nextPlace(currentPlace);

	}

	/**
	 * Tries to pick an item characterized by a given identifier from the
	 * current place. If the action was completed the item is removed from the
	 * current place.
	 * 
	 * @param id
	 *            - The identifier of the item
	 * @return The item of identifier id if it exists in the place. Otherwise
	 *         the method returns null
	 */
	public Item pickItemFromCurrentPlace(java.lang.String id) {

		return currentPlace.pickItem(id);
	}

	/**
	 * Drop an item in the current place. It assumes that there is no other item
	 * with the same name/id there. Otherwise, the behaviour is undefined.
	 * 
	 * @param item
	 *            - The name of the item to be dropped.
	 */
	public void dropItemAtCurrentPlace(Item it) {
		currentPlace.addItem(it);
	}

	/**
	 * Checks if there is an item with a given id in this place
	 * 
	 * @param id
	 *            - Identifier of the item we are looking for
	 * @return true if and only if an item with this id is in the current place
	 */
	public boolean findItemAtCurrentPlace(java.lang.String id) {
		return currentPlace.existItem(id);
	}

	/**
	 * Initializes the current heading according to the parameter
	 * 
	 * @param heading
	 *            - New direction for the robot
	 */
	public void initHeading(Direction heading) {
		currentDirection = heading;
	}

	/**
	 * Prints the information (description + inventory) of the current place
	 */
	public void scanCurrentPlace() {
		System.out.println(currentPlace.toString());
	}

	/**
	 * Returns the street opposite the robot
	 * 
	 * @return the street opposite the robot or null if there's not exist a
	 *         street
	 */
	public Street getHeadingStreet() {
		return cityMap.lookForStreet(currentPlace, currentDirection);
	}

	/**
	 * Returns the robot heading
	 * 
	 * @return The direction where the robot is facing to.
	 */
	public Direction getCurrentHeading() {
		return currentDirection;
	}
	
	/**
	 * Returns the current place where the robot is (for testing purposes)
	 * @return The current place
	 */
	public Place getCurrentPlace(){
		return currentPlace;
	}
}
